﻿@page "/weather"

@using Bit.Besql.Demo.Client.Model
@using Microsoft.EntityFrameworkCore
@using Bit.Besql.Demo.Client.Data

@inject HttpClient HttpClient;
@inject IBitBesqlStorage BitBesqlStorage;
@inject IDbContextFactory<OfflineDbContext> DbContextFactory

<PageTitle>Bit Besql weather forecast sample</PageTitle>

<button class="btn btn-primary" @onclick="ReadData">Read data</button>
<button class="btn btn-primary" @onclick="AddData">Add data</button>
<button class="btn btn-primary" @onclick="BatchOperations">Batch operations</button>
<button class="btn btn-primary" @onclick="PauseResumePersistent">Pause / resume persistent</button>
<button class="btn btn-primary" @onclick="UsePrePopulatedDatabase">Use pre populated database</button>
<button class="btn btn-primary" @onclick="ReCreateDatabase">Re-create database</button>
<button class="btn btn-primary" @onclick="Backup">Backup</button>

<h1>@forecastsCount</h1>

@code {

    private int? forecastsCount;

    private async Task ReadData()
    {
        await using var dbContext = await DbContextFactory.CreateDbContextAsync();
        forecastsCount = await dbContext.WeatherForecasts.CountAsync();
    }

    private async Task AddData()
    {
        await using var dbContext = await DbContextFactory.CreateDbContextAsync();
        await dbContext.WeatherForecasts.AddAsync(new()
        {
            Date = new DateTimeOffset(2024, 1, 4, 10, 10, 10, TimeSpan.Zero),
            Summary = "A B C D E F G H I J K L M N O P Q R S T U V W X Y Z a b c d e f g h i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S T U V W X Y Z a b c d e f g h i j k l m n o p q r s t u v w x y zA B C D E F G H I J K L M N O P Q R S T U V W X Y Z a b c d e f g h i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S T U V W X Y Z a b c d e f g h i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S T U V W X Y Z a b c d e f g h i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S T U V W X Y Z a b c d e f g h i j k l m n o p q r s t u v w x y zA B C D E F G H I J K L M N O P Q R S T U V W X Y Z a b c d e f g h i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S T U V W X Y Z a b c d e f g h i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S T U V W X Y Z a b c d e f g h i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S T U V W X Y Z a b c d e f g h i j k l m n o p q r s t u v w x y zA B C D E F G H I J K L M N O P Q R S T U V W X Y Z a b c d e f g h i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S T U V W X Y Z a b c d e f g h i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S T U V W X Y Z a b c d e f g h i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S T U V W X Y Z a b c d e f g h i j k l m n o p q r s t u v w x y zA B C D E F G H I J K L M N O P Q R S T U V W X Y Z a b c d e f g h i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S T U V W X Y Z a b c d e f g h i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S T U V W X Y Z a b c d e f g h i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S T U V W X Y Z a b c d e f g h i j k l m n o p q r s t u v w x y zA B C D E F G H I J K L M N O P Q R S T U V W X Y Z a b c d e f g h i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S T U V W X Y Z a b c d e f g h i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S T U V W X Y Z a b c d e f g h i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S T U V W X Y Z a b c d e f g h i j k l m n o p q r s t u v w x y zA B C D E F G H I J K L M N O P Q R S T U V W X Y Z a b c d e f g h i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S T U V W X Y Z a b c d e f g h i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S T U V W X Y Z a b c d e f g h i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S T U V W X Y Z a b c d e f g h i j k l m n o p q r s t u v w x y zA B C D E F G H I J K L M N O P Q R S T U V W X Y Z a b c d e f g h i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S T U V W X Y Z a b c d e f g h i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S T U V W X Y Z a b c d e f g h i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S T U V W X Y Z a b c d e f g h i j k l m n o p q r s t u v w x y zA B C D E F G H I J K L M N O P Q R S T U V W X Y Z a b c d e f g h i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S T U V W X Y Z a b c d e f g h i j k l m n o p q r s t u v w x y z ",
            TemperatureC = Random.Shared.Next(1, 30)
        });
        await dbContext.WeatherForecasts.AddAsync(new()
        {
            Date = new DateTimeOffset(2024, 1, 4, 10, 10, 10, TimeSpan.Zero),
            Summary = "Test",
            TemperatureC = Random.Shared.Next(1, 30)
        });
        await dbContext.SaveChangesAsync();

        await ReadData();
    }

    private async Task BatchOperations()
    {
        await using var dbContext = await DbContextFactory.CreateDbContextAsync();
        var deletedCount = await dbContext.WeatherForecasts
            .Where(w => w.TemperatureC % 2 == 0)
            .ExecuteDeleteAsync();
        deletedCount += await dbContext.WeatherForecasts
            .Where(w => w.TemperatureC % 3 == 0)
            .ExecuteDeleteAsync();

        await ReadData();
    }

    private async Task PauseResumePersistent()
    {
        BitBesqlStorage.PauseAutomaticPersistent();

        try
        {
            await AddData();

            await Task.Delay(5_000);

            await AddData();
        }
        finally
        {
            await BitBesqlStorage.ResumeAutomaticPersistent();
        }

        await ReadData();
    }

    private async Task UsePrePopulatedDatabase()
    {
        // This feature can alternatively be implemented as an API that dynamically fills a SQLite database.
        // Note: If the `dbContext` used to populate the SQLite database file is not instantiated by `bit Besql`,
        // you must manually call `dbContext.Database.ConfigureSqliteJournalMode()`.
        await using var prePopulatedDatabase = await HttpClient.GetStreamAsync("https://localhost:5050/Pre-Populated-Offline-Client.db");

        var fileName = "Offline-Client.db";
        await using (var fileStream = new FileStream(fileName, FileMode.Create, FileAccess.Write))
        {
            await prePopulatedDatabase.CopyToAsync(fileStream);
        }
        await BitBesqlStorage.Persist(fileName);

        await ReadData();
    }

    private async Task ReCreateDatabase()
    {
        await using var dbContext = await DbContextFactory.CreateDbContextAsync();

        await dbContext.Database.EnsureDeletedAsync();

        // This method is automatically invoked by Besql the first time the app runs.
        // If you need to drop and recreate the database multiple times within the same app session, you must call this method manually.
        await dbContext.Database.ConfigureSqliteJournalMode();

        await dbContext.Database.MigrateAsync();
    }

    private async Task Backup()
    {

        {
            await using var dbContext = await DbContextFactory.CreateDbContextAsync();
            await using var sourceStream = File.OpenRead("Offline-Client.db");
            await using var destinationStream = File.OpenWrite("Offline-Client2.db"); // You can upload the file to a server or cloud storage.
            await sourceStream.CopyToAsync(destinationStream);
        }

        await using var testDbContext = new OfflineDbContext(new DbContextOptionsBuilder<OfflineDbContext>()
            .UseSqlite("Data Source=Offline-Client2.db")
            .Options);

        forecastsCount = await testDbContext.WeatherForecasts.CountAsync();
    }
}
